
#include <BReadWrite>
#include <BSplitter>
#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BFileDialog>
#include <BShape>
#include <BGeometry>
#include <BMesh>
#include <BStyle>
#include <BMessageBox>

#include "MainDialog.h"

MainDialog::MainDialog()
{
	BHBoxLayout* buttonLayout = new BHBoxLayout();
	{
		_importButton = new BButton("import");
		_exportButton = new BButton("export");
		_resetButton = new BButton("reset");

		buttonLayout->addWidget(_importButton);
		buttonLayout->addWidget(_exportButton);
		buttonLayout->addWidget(_resetButton);
		buttonLayout->addSpring();
	}

	_sceneTree = new BTreeWidget();

	_camera = new BCamera();
	_control = new BSphereControl();
	_scene = new BScene();

	_viewer = new BViewer();
	_viewer->setControl(_control);
	_viewer->setCamera(_camera);
	_viewer->setScene(_scene);

	BSplitter* splitter = new BSplitter();
	splitter->setHeightStretch(100);
	splitter->addWidget(_sceneTree);
	splitter->addWidget(_viewer);

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addLayout(buttonLayout);
	vlayout->addWidget(splitter);

	connect(_importButton, Signal_Clicked, &MainDialog::slotImportFile);
	connect(_exportButton, Signal_Clicked, &MainDialog::slotExportFile);
	connect(_resetButton, Signal_Clicked, &MainDialog::slotResetScene);
}
MainDialog::~MainDialog()
{

}

void MainDialog::slotImportFile()
{
	const BString& fileName = BFileDialog::OpenFileName(this, "Import File", "./data/scene");
	if (fileName.size())
	{
		BScene* scene = Read<BScene>(fileName);
		if (!scene)
		{
			BMessageBox::information(this, "Information", "Import Scene file failed !", Button_Ok, Button_Ok);
			return;
		}

		for (int i = 0; i < scene->shapeCount(); i++)
		{
			BShape* shape = scene->shape(i);
			_scene->inserts(shape);
			BTreeItem* topItem = _sceneTree->addTopItem(shape->name());
			topItem->setValue(shape);
			topItem->setImage(_shapeImage);
			if (BGeometry* geometry = dynamic_cast<BGeometry*>(shape))
			{
				for (int ei = 0; ei < geometry->elementCount(); ei++)
				{
					BElement* element = geometry->element(ei);
					BTreeItem* elementItem = topItem->addChild(primName(element->primitive()));
					elementItem->setValue(element);
					elementItem->setImage(_elementImage);
				}
			}
		}
		for (int i = 0; i < scene->nodeCount(); i++)
		{
			BNode* node = scene->node(i);
			_scene->inserts(node);
			BTreeItem* topItem = _sceneTree->addTopItem(node->name());
			topItem->setValue(node);
			topItem->setImage(_nodeImage);
			for (int i = 0; i < node->shapeCount(); i++)
			{
				BShape* shape = node->shape(i);
				BTreeItem* shapeItem = new BTreeItem(shape->name(), topItem);
				shapeItem->setValue(shape);
				shapeItem->setImage(_shapeImage);
				if (BGeometry* geometry = dynamic_cast<BGeometry*>(shape))
				{
					for (int ei = 0; ei < geometry->elementCount(); ei++)
					{
						BElement* element = geometry->element(ei);
						BTreeItem* elementItem = shapeItem->addChild(primName(element->primitive()));
						elementItem->setValue(element);
						elementItem->setImage(_elementImage);
					}
				}
			}

		}

		BSpace space = _scene->space();
		float near = space.radius() * 0.01f;
		_camera->setNear(bMin(1.0f, near));
		_camera->setFar(space.radius() * 100);
	}
}
void MainDialog::slotExportFile()
{
	const BString& fileName = BFileDialog::OpenFileName(this, "Import File", "./data/scene");
	if (fileName.size())
	{
		if (Write<BScene>(fileName, _scene))
		{
			BMessageBox::information(this, "Information", "Export Scene file successful !", Button_Ok, Button_Ok);
		}
		else
		{
			BMessageBox::information(this, "Information", "Export Scene file failed !", Button_Ok, Button_Ok);
		}
	}
}
void MainDialog::slotResetScene()
{
	_sceneTree->clearItems();
	_scene->clear();
}

void MainDialog::styleEvent(const BEvent& event)
{
	BStyle* style = this->realStyle();
	if (style)
	{
		_nodeImage = style->image("node");
		_shapeImage = style->image("shape");
		_elementImage = style->image("element");
	}
	else
	{
		_nodeImage = 0;
		_shapeImage = 0;
		_elementImage = 0;
	}

}

const char* MainDialog::primName(Primitive prim)
{
	switch (prim)
	{
	case Primitive_Points:
		return "Points";
	case Primitive_Lines:
		return "Lines";
	case Primitive_LineStrip:
		return "LineStrip";
	case Primitive_LineLoop:
		return "LineLoop";
	case Primitive_Triangles:
		return "Triangles";
	case Primitive_TriangleStrip:
		return "TriangleStrip";
	case Primitive_TriangleFan:
		return "TriangleFan";
	case Primitive_Quads:
		return "Quads";
	case Primitive_QuadStrip:
		return "QuadStrip";
	case Primitive_Polygon:
		return "Polygon";
	default:
		return "None";
	}
}
